<!DOCTYPE html>
<html>
<head>
    <th:block th:include="include :: header('选项卡 & 面板')"/>
    <!--需要放在 后面 不然会被 前者的style覆盖-->
    <link th:href="@{/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet"/>
    <link th:href="@{/css/font-awesome.min.css?v=4.7.0}" rel="stylesheet"/>
    <!-- bootstrap-table 表格插件样式 -->
    <link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css?v=1.18.3}" rel="stylesheet"/>
    <link th:href="@{/css/animate.min.css?v=20210831}" rel="stylesheet"/>
    <link th:href="@{/css/style.min.css?v=20210831}" rel="stylesheet"/>
    <link th:href="@{/ruoyi/css/ry-ui.css?v=4.7.7}" rel="stylesheet"/>
    <link href="/css/map/switch.css" rel="stylesheet"/>
    <link href="/css/map/info-card.css" rel="stylesheet">
    <link rel="stylesheet" href="/ajax/libs/layui-v2.8.4/css/layui.css">
    <link rel="stylesheet" href="/ajax/libs/layui-v2.8.4/css/layui-theme-dark.css">
    <link href="/css/map/device.css" rel="stylesheet">
    <link href="/ajax/libs/ol-6.9.0/ol.css" rel="stylesheet"/>
    <link href='/ajax/libs/sm-11.1.0/iclient-ol.min.css' rel='stylesheet'/>
    <style>
        .nav-tabs > li > a {
            color: #ffffff;
        }

        .nav-tabs > li.active > a,
        .nav-tabs > li.active > a:hover,
        .nav-tabs > li.active > a:focus {
            color: #ffffff;
        }

        .param {
            display: none;
        }

        .ol-popup {
            position: absolute;
            top: 0;
            right: 10px;
            padding: 0 10px;
        }

        .ol-attribution, .ol-control-logo {
            display: none;
        }

        .date-input {
            text-align: center;
        }

        .data-control-area {
            display: none;
        }

        #edit-path-btn {
            float: right;
            margin-right: 10px;
        }

        #save-path-btn {
            float: right;
            margin-right: 10px;
        }

        #remove-path-btn {
            float: right;
            margin-right: 10px;
        }

        #add-path-btn {
            float: right;
            margin-right: 10px;
        }

        #send-path-btn {
            float: right;
            margin-right: 10px;
        }

        .indicate-route-color {
            display: none;
            position: absolute;
            bottom: 10px;
            right: 10px;
            background-color: rgba(0, 0, 0, 0.5);
            padding: 5px;
            border-radius: 4px;
            color: #ffffff;
        }

        .indicate-color-mean {
            display: inline-block;
            height: 16px;
            vertical-align: middle;
        }

        .indicate-color {
            display: inline-block;
            width: 20px;
            height: 16px;
            vertical-align: middle;
            margin-right: 10px;
        }

        .indicate-color-new {
            background-color: #4caf50;
        }

        .indicate-color-nav {
            background-color: #504caf;
        }

        .indicate-color-cancel {
            background-color: #af4cab;
        }

        .indicate-color-complete {
            background-color: #af504c;
        }

        .indicate-color-edit {
            background-color: #abaf4c;
        }

        .select-list li select {
            border: 1px solid rgba(255, 255, 255, 0.3);
            border-radius: 15px;
            background: transparent;
            outline: none;
            height: 30px;
            width: 100px;
            color: #fff;
        }

        .select-list li select option {
            background-color: rgba(25, 30, 33);
        }
    </style>
</head>
<body>
<div class="param boat-id">[[${boat.id}]]</div>
<div class="param boat-code">[[${boat.code}]]</div>
<div class="wrapper">
    <div class="row chart-title"></div>
    <div class="row">
        <div class="col-sm-12">
            <div id="map" style="width: 100%; background-color:rgba(0,0,0,0.5)">
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-sm-12">
            <div class="panel blank-panel">
                <div class="panel-heading">
                    <div class="panel-options">
                        <ul class="nav nav-tabs">
                            <li class="active">
                                <a data-toggle="tab" href="#auto-ship"><i class="fa fa-anchor"></i>&#12288;航迹相关</a>
                            </li>
                            <li class="">
                                <a data-toggle="tab" href="#manual-ship"><i class="fa fa-search"></i>&#12288;查询轨迹</a>
                            </li>
                        </ul>
                    </div>
                </div>

                <div class="panel-body">
                    <div class="tab-content">
                        <!-- 历史轨迹开始 -->
                        <div id="manual-ship" class="tab-pane">
                            <div class="row">
                                <div class="col-sm-6">
                                    <!-- 通过开始时间和结束时间查询轨迹、清除轨迹-->
                                    <div>
                                        <input type="text" class="beginTime date-input" style="width: 150px"
                                               placeholder="开始时间"/>
                                        <input type="text" class="endTime date-input" style="width: 150px"
                                               placeholder="结束时间"/>
                                        <button type="button" class="searchBtn btn btn-primary btn-rounded btn-sm"
                                                onclick="searchTrack()">
                                            <i class="fa fa-search"></i>
                                            搜索
                                        </button>
                                        <button type="button" class="clearBtn btn btn-warning btn-rounded btn-sm"
                                                onclick="clearTrack()">
                                            <i class="fa fa-remove"></i>
                                            清空
                                        </button>
                                    </div>
                                </div>
                                <div class="col-sm-6 data-control-area">
                                    <!-- 导出轨迹数据 轨迹动画（开始、暂停、加速、减速、重播）-->
                                    <button type="button" class="controlBtn btn btn-primary btn-rounded btn-sm">
                                        <i class="fa fa-play"></i>
                                    </button>
                                    <label style="color: #ffffff">播放速度:&nbsp;</label>
                                    <label><input id="speed" type="range" min="2" max="10" step="2" value="6"></label>
                                    <button type="button" class="export btn btn-success btn-rounded btn-sm">
                                        <i class="fa fa-cloud-download"></i>
                                        下载轨迹数据
                                    </button>
                                </div>
                            </div>
                        </div>
                        <!-- 航迹开始 -->
                        <div id="auto-ship" class="tab-pane active">
                            <div class="row search-row" id="toolbar">
                                <div class="col-sm-12">
                                    <form id="formId">
                                        <div class="select-list">
                                            <ul>
                                                <li><input type="text" class="beginTime date-input"
                                                           placeholder="开始时间"/></li>
                                                <li><input type="text" class="endTime date-input"
                                                           placeholder="结束时间"/></li>
                                                <li>
                                                    <select name="route-status"
                                                            th:with="type=${@dict.getType('sys_route_status')}">
                                                        <option value="">航线状态：</option>
                                                        <option th:each="dict : ${type}" th:text="${dict.dictLabel}"
                                                                th:value="${dict.dictValue}"></option>
                                                    </select>
                                                </li>
                                            </ul>
                                        </div>
                                        <button type="button" class="btn btn-primary btn-rounded btn-sm"
                                                onclick="searchRoute()">
                                            <i class="fa fa-search"></i>
                                        </button>
                                        <button type="button" class="btn btn-warning btn-rounded btn-sm"
                                                onclick="refreshRouteTable()">
                                            <i class="fa fa-refresh"></i>
                                        </button>
                                        <button type="button" class="btn btn-danger btn-rounded btn-sm"
                                                onclick="removeRoute()">
                                            <i class="fa fa-remove"></i>
                                        </button>
                                        <!-- <button type="button" class="btn btn-success btn-rounded btn-sm"
                                                 onclick="">
                                             <i class="fa fa-cloud-download"></i>
                                         </button>-->
                                        <button type="button" class="btn btn-success btn-rounded btn-sm"
                                                id="remove-path-btn" onclick="cleanRoute()">
                                            <i class="fa fa-eraser"></i>
                                        </button>
                                        <button type="button" class="btn btn-success btn-rounded btn-sm"
                                                id="send-path-btn" onclick="sendRoute()">
                                            <i class="fa fa-send"></i>
                                        </button>
                                        <button type="button" class="btn btn-success btn-rounded btn-sm"
                                                id="save-path-btn" onclick="saveRoute()">
                                            <i class="fa fa-save"></i>
                                        </button>
                                        <button type="button" class="btn btn-success btn-rounded btn-sm"
                                                id="edit-path-btn" onclick="modifyRoute()">
                                            <i class="fa fa-edit"></i>
                                        </button>
                                        <button type="button" class="btn btn-success btn-rounded btn-sm"
                                                id="add-path-btn" onclick="createRoute()">
                                            <i class="fa fa-plus"></i>
                                        </button>
                                    </form>
                                </div>
                            </div>
                            <div class="col-sm-12" id="table-row">
                                <table id="bootstrap-table"></table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div id="popup" class="ol-popup">
        <div class="btn-group" role="group" aria-label="...">
<!--            <button id="mock" value='Mock' type="button" class="btn btn-default">模拟点位更新</button>-->
            <button id="measure" value='Measure' type="button" class="btn btn-default">测距</button>
            <button id="clear" value='Clear' type="button" class="btn btn-default">清除</button>
            <button id="see-map" value='SeeMap' type="button" class="btn btn-default see-map-show">海图</button>
        </div>
    </div>
    <div class="indicate-route-color">
        <div><label class="indicate-color indicate-color-nav"></label>航线在用</div>
        <div class="indicate-box"><label class="indicate-color indicate-color-cancel"></label><label
                class="indicate-color-mean">航线取消</label></div>
        <div class="indicate-box"><label class="indicate-color indicate-color-edit"></label>航线编辑</div>
        <div class="indicate-box"><label class="indicate-color indicate-color-complete"></label>航线结束</div>
        <div class="indicate-box"><label class="indicate-color indicate-color-new"></label>航线新建</div>
    </div>
</div>
<script th:inline="javascript">
    var mapHost = [[${mapHost}]];
</script>
<script th:src="@{/js/jquery.min.js?v=3.6.3}"></script>
<script th:src="@{/js/bootstrap.min.js?v=3.3.7}"></script>
<!-- bootstrap-table 表格插件 -->
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=1.18.3}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js?v=1.18.3}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js?v=1.18.3}"></script>
<!-- jquery-validate 表单验证插件 -->
<script th:src="@{/ajax/libs/validate/jquery.validate.min.js?v=1.19.3}"></script>
<script th:src="@{/ajax/libs/validate/jquery.validate.extend.js?v=1.19.3}"></script>
<script th:src="@{/ajax/libs/validate/messages_zh.js?v=1.19.3}"></script>
<!-- bootstrap-table 表格树插件 -->
<script th:src="@{/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js?v=1.18.3}"></script>
<!-- 遮罩层 -->
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js?v=2.70.0}"></script>
<script th:src="@{/ajax/libs/iCheck/icheck.min.js?v=1.0.3}"></script>
<!--    <script th:src="@{/ajax/libs/layer/layer.min.js?v=3.5.1}"></script>-->
<!--    <script th:src="@{/ajax/libs/layui/layui.min.js?v=2.7.5}"></script>-->
<script th:src="@{/ruoyi/js/common.js?v=4.7.7}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.7.7}"></script>
<script src="/ajax/libs/chartjs/chart.umd.min.js?v=4.3.3"></script>
<script src="/ajax/libs/layui-v2.8.4/layui.js"></script>
<script src="/ajax/libs/dayjs/dayjs.min.js?v=1.8.21"></script>
<script src="/ajax/libs/report/sparkline/mysparkline.js"></script>
<script type="text/javascript" src="/ajax/libs/ol-6.9.0/ol.js"></script>
<script type="text/javascript" src="/ajax/libs/sm-11.1.0/iclient-ol.min.js"></script>
<script type="text/javascript" src="/js/map/data.js"></script>
<script type="text/javascript" src="/js/map/map-util.js"></script>
<script type="text/javascript" src="/js/map/map.js"></script>
<script th:inline="javascript">
    //设置map高度
    windowResizeCallback();
    initMap();
    //初始化laydateUI
    var laydate = layui.laydate;
    laydate.render({
        elem: '.beginTime',
        type: 'datetime',
        trigger: 'click'
    });
    laydate.render({
        elem: '.endTime',
        type: 'datetime',
        trigger: 'click'
    });
    var prefix = "/boat/path";
    var options = {
        url: prefix + "/list",
        showSearch: false,
        showRefresh: false,
        showColumns: false,
        showToggle: false,
        singleSelect: true,
        queryParamsType: '',
        queryParams: queryTableParams,
        sortName: 'id',
        sortOrder: 'desc',
        sidePagination: 'server',
        onLoadSuccess: function (data) {
            dataList = data.rows;
            //渲染第一个path
            if (!$.common.isEmpty(dataList)) {
                try {
                    selectedRoute = dataList[0];
                    getRouteAndDraw(dataList[0]);
                    var currentStatus = [[${status}]];
                    showBoatFeature(boatPointSource, map, getBoatGeoInfo([currentStatus]));
                } catch (e) {
                    console.log(e)
                }
            }
        },
        onClickCell: function (field, value, row, $element) {
            //点击某一行 做出处理
            selectedRoute = row;
            getRouteAndDraw(row);
        },
        columns: [
            {
                checkbox: true,
            },
            {
                field: 'name',
                title: '路线名称',
            },
            {
                field: 'status',
                title: '状态',
                formatter: function (value, item, index) {
                    if (value === routeType.cancelRoute) {
                        return "航线取消";
                    } else if (value === routeType.newRoute) {
                        return "航线新建";
                    } else if (value === routeType.navRoute) {
                        return "航线在用";
                    } else if (value === routeType.completeRoute) {
                        return "航线结束";
                    }
                }
            },
            {
                field: 'beginTime',
                title: '开始时间'
            },
            {
                field: 'endTime',
                title: '结束时间'
            }
        ]
    };
    $.table.init(options);

    function queryTableParams(params) {
        return {
            pageSize: params.pageSize,
            pageNum: params.pageNum,
            boatCode: [[${boat.code}]],
            beginTime: $("#auto-ship .beginTime").val(),
            endTime: $("#auto-ship .endTime").val(),
            status: $("select[name='route-status'] option:selected").val()
        }
    }

    function windowResizeCallback() {
        $('#map').height($('#map').width() * 2 / 4);
    }

    //用于处理 websocket
    var msgType = 'status';

    function msgGot(object) {
        if (object.type !== msgType || object.data.boatCode !== [[${boat.code}]]) return;
        var newStatus = object.data;
        //更新点位
        updateBoatFeature(newStatus);
        //todo 根据是否需要描绘实时轨迹(可勾选)，来画线
    }

    //用于编辑航迹各个变量
    var selectedRoute = {};
    //这里为了能够给航线新增路线，所以用了两个source
    //其中 modify 用于对未发送和正在编辑的航线
    //const 用于已经发送了的航线
    let source_modify = new ol.source.Vector();
    let source_const = new ol.source.Vector();
    let snap = new ol.interaction.Snap({
        source: source_modify,
    });
    let snap_const = new ol.interaction.Snap({
        source: source_const,
    });
    let modify = new ol.interaction.Modify({
        source: source_modify,
    });
    //每个vector 只能对应一个 source，所以此处用两个 ， 而且modify需要放在const的上面
    let vector_const = new ol.layer.Vector({
        source: source_const,
    });
    let vector_modify = new ol.layer.Vector({
        source: source_modify,
    });
    let drawing = false;
    //用于绘制
    let draw = new ol.interaction.Draw({
        source: source_modify,
        type: "LineString"
    });
    draw.on('drawend', function (e) {
        var theRouteFeature = getTheRouteFeature(source_modify.getFeatures());
        if (theRouteFeature === undefined) {
            if (source_const.getFeatures().length === 0) {
                e.feature.setStyle(getLineStyle(colorOption.newRoute, 2));
                e.feature.set('routeType', routeType.newRoute);
            } else {
                e.feature.setStyle(getLineStyle(colorOption.editRoute, 2));
                combineLineString(e.feature);
            }
        } else {
            e.feature.setStyle(getLineStyle(colorOption.editRoute, 2));
            combineLineString(e.feature);
        }
    });
    modify.on('modifyend', function (e) {
        console.log("modifyend");
        if (e.features.getLength() !== 1) return;
        var modifyFeature = e.features.getArray().at(0);
        if (modifyFeature.get('routeType') !== routeType.newRoute) {
            //只有对非theRoute modify 的时候才会 去尝试combineLineString
            combineLineString(e.features.pop());
        }
        var constCoordinates = getCoordinateFromSource(source_const);
        var modifyCoordinates = modifyFeature.getGeometry().getCoordinates();
        if (modifyFeature.get('routeType') === routeType.newRoute) {
            if (constCoordinates.length > 0 && modifyCoordinates.length > 0
                && !isSamePoint(constCoordinates.at(-1), modifyCoordinates[0])) {
                //对theRoute操作且具有已经发送了的路线时 需要考虑是不是 会出现脱节 constFeature
                modifyFeature.set('routeType', undefined);
                modifyFeature.setStyle(getLineStyle(colorOption.editRoute, 2));
            }
        }
    });

    function combineLineString(feature) {
        console.log("combine");
        var feature_const = source_const.getFeatures();
        var feature_modify = source_modify.getFeatures();
        var coordinates = feature.getGeometry().getCoordinates();
        var theRouteFeature = getTheRouteFeature(feature_modify);
        if (theRouteFeature !== undefined) {
            //新建路劲还未发送过
            var theRouteCoordinates = theRouteFeature.getGeometry().getCoordinates();
            var lastPoint = theRouteCoordinates.at(-1);
            var secondToLastPoint = theRouteCoordinates.at(-2);
            if (isSamePoint(coordinates[0], lastPoint)) {
                for (let i = 1; i < coordinates.length; i++) {
                    theRouteCoordinates.push(coordinates[i]);
                }
                setTimeout(function () {
                    source_modify.removeFeature(feature);
                    source_modify.removeFeature(theRouteFeature);
                    addFeatureToSource(source_modify, colorOption.newRoute, theRouteCoordinates, routeType.newRoute);
                }, 10);//需要等待一段时间，因为drawend中feature添加到source是自动的所以可能会出现 在还没有自动添加的时候就删除的情况
            } else if (isSamePoint(coordinates.at(-1), lastPoint)) {
                for (let i = coordinates.length - 2; i >= 0; i--) {
                    theRouteCoordinates.push(coordinates[i]);
                }
                setTimeout(function () {
                    source_modify.removeFeature(feature);
                    source_modify.removeFeature(theRouteFeature);
                    addFeatureToSource(source_modify, colorOption.newRoute, theRouteCoordinates, routeType.newRoute);
                }, 10);
            }
        } else if (feature_const.length > 0 && theRouteFeature === undefined) {
            //已经发送过的路劲，还没跑完现在要添加后续的点位
            var constCoordinates = feature_const[0].getGeometry().getCoordinates();
            var lastPoint = constCoordinates.at(-1);
            var theRouteCoordinates = [];
            if (isSamePoint(coordinates[0], lastPoint)) {
                for (let i = 0; i < coordinates.length; i++) {
                    theRouteCoordinates.push(coordinates[i]);
                }
                setTimeout(function () {
                    source_modify.removeFeature(feature);
                    addFeatureToSource(source_modify, colorOption.newRoute, theRouteCoordinates, routeType.newRoute);
                }, 10);//需要等待一段时间，因为drawend中feature添加到source是自动的所以可能会出现 在还没有自动添加的时候就删除的情况
            } else if (isSamePoint(coordinates.at(-1), lastPoint)) {
                for (let i = coordinates.length - 1; i >= 0; i--) {
                    theRouteCoordinates.push(coordinates[i]);
                }
                setTimeout(function () {
                    source_modify.removeFeature(feature);
                    addFeatureToSource(source_modify, colorOption.newRoute, theRouteCoordinates, routeType.newRoute);
                }, 10);
            }
        }
    }

    /**
     * 获得 一条航线中可编辑的部分
     * @param feature_modify
     * @returns {undefined}
     */
    function getTheRouteFeature(feature_modify) {
        var theRouteFeature = undefined;
        feature_modify.forEach(function (f) {
            if (f.get('routeType') === routeType.newRoute) {
                theRouteFeature = f;
            }
        });
        return theRouteFeature;
    }

    function initMap() {
        //加载地图
        loadMap(sourceUrlList, bounds).then(map => {
            this.map = map;
            //拥有了map之后才添加
            map.addLayer(vector_const);
            map.addLayer(vector_modify);
            var currentStatus = [[${status}]];
            showBoatFeature(boatPointSource, map, getBoatGeoInfo([currentStatus]));
            map.getView().on('change:resolution', resolutionChangeListener);

            // 监听鼠标右键点击事件，在右键点击时取消绘制
            map.getViewport().addEventListener('contextmenu', function (event) {
                if (drawing) {
                    event.preventDefault(); // 阻止默认右键菜单弹出
                    map.removeInteraction(draw);
                    map.removeInteraction(modify);
                    map.removeInteraction(snap);
                    map.removeInteraction(snap_const);
                    drawing = false; // 标记绘制结束
                }
            });
            $(".indicate-route-color").css('display', "block");
            var indicateColor = new ol.control.Control({
                element: $('.indicate-route-color')[0],
            });
            map.addControl(indicateColor);
        });
    }

    let colorOption = {
        "navRoute": "#504caf",//艇正在行驶的航迹
        "newRoute": "#4caf50",//可编辑的航迹
        "editRoute": "#abaf4c",//后续新增的航迹
        "completeRoute": "#af504c",//行驶结束的航迹
        "cancelRoute": "#af4cab",//取消的轨迹
        "historyTrack": "#795548"//历史轨迹
    }

    function getLineStyle(color, width) {
        return new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: color,
                width: width
            })
        });
    }

    let routeType = {
        "completeRoute": 0,
        "navRoute": 1,
        "editRoute": 2,
        "cancelRoute": 3,
        "newRoute": 4,
    };

    //==============历史轨迹JS==============//
    var routeFeature;
    var startFeature;
    var endFeature;
    var geoFeature;
    var routeGeometry;
    var position;
    var vectorLayer;

    var styles = {
        'route': new ol.style.Style({
            stroke: new ol.style.Stroke({
                width: 2,
                color: colorOption.historyTrack,
            }),
        }),
        'startIcon': new ol.style.Style({
            image: new ol.style.Icon({
                anchor: [0.5, 1],
                src: '/img/icon/startPoint.svg',
            }),
        }),
        'endIcon': new ol.style.Style({
            image: new ol.style.Icon({
                anchor: [0.5, 1],
                src: '/img/icon/endPoint.svg'
            })
        }),
        'geoMarker': new ol.style.Style({
            image: new ol.style.Circle({
                radius: 7,
                fill: new ol.style.Fill({color: '#ffffff'}),
                stroke: new ol.style.Stroke({
                    color: '#ff893b',
                    width: 1,
                }),
            }),
        }),
    };

    function searchTrack() {
        var boatCode = $(".boat-code").html();
        var beginTime = $("#manual-ship .beginTime").val();
        var endTime = $("#manual-ship .endTime").val();
        if (beginTime === '' || endTime === '') {
            layer.alert("请输入起始时间和结束时间");
            return;
        }
        $.ajax({
            type: "POST",
            url: "/boat/status/list",
            dataType: "json",
            data: [{"name": "params[beginTime]", "value": beginTime},
                {"name": "params[endTime]", "value": endTime},
                {"name": "boatCode", "value": boatCode}],
            success: function (response) {
                console.log(response.rows);
                if (response.code === 0) {
                    if (response.total > 0) {
                        //处理
                        var statusList = response.rows;
                        var coordinates = [];
                        statusList.forEach(function (item) {
                            coordinates.push([item.lng, item.lat]);
                        });
                        routeGeometry = new ol.geom.LineString(coordinates);
                        routeFeature = new ol.Feature({
                            type: 'route', geometry: routeGeometry
                        });
                        startFeature = new ol.Feature({
                            type: 'startIcon',
                            geometry: new ol.geom.Point(routeGeometry.getFirstCoordinate())
                        });
                        endFeature = new ol.Feature({
                            type: 'endIcon',
                            geometry: new ol.geom.Point(routeGeometry.getLastCoordinate())
                        });
                        position = startFeature.getGeometry().clone();
                        geoFeature = new ol.Feature({
                            type: 'geoMarker',
                            geometry: position
                        });
                        vectorLayer = new ol.layer.Vector({
                            source: new ol.source.Vector({
                                features: [routeFeature, geoFeature, startFeature, endFeature]
                            }),
                            style: function (feature) {
                                return styles[feature.get('type')]
                            }
                        });
                        map.addLayer(vectorLayer);
                        $(".data-control-area").css({"display": "block"})
                    } else {
                        //弹窗
                        layer.alert("再此时间段内无记录！");
                    }
                }
            },
            error: function (xhr, status, error) {
                console.log("Request failed with status:" + status);
            }
        });
    }

    let animating = false;
    let distance = 0;
    let lastTime;
    let stop = false;//是否轨迹运行结束

    function moveFeature(event) {
        const speed = Number($("#speed").val());
        const time = event.frameState.time;
        const elapsedTime = time - lastTime;
        distance = (distance + (speed * elapsedTime) / 1e5) % 2;
        lastTime = time;
        distance = distance > 1 ? 1 : distance;
        const currentCoordinate = routeGeometry.getCoordinateAt(
            distance
        );
        position.setCoordinates(currentCoordinate);
        const vectorContext = new ol.render.getVectorContext(event);
        vectorContext.setStyle(styles.geoMarker);
        vectorContext.drawGeometry(position);
        map.render();
        if (distance === 1) {
            //到达终点，动画结束
            stopAnimation();
            stop = true;
        }
    }

    function startAnimation() {
        if (vectorLayer == null) {
            return;
        }
        animating = true;
        $(".controlBtn > i").removeClass("fa-play").addClass("fa-stop");
        lastTime = Date.now();
        vectorLayer.on('postrender', moveFeature);
        geoFeature.setGeometry(null);
    }

    function stopAnimation() {
        animating = false;
        $(".controlBtn > i").removeClass("fa-stop").addClass("fa-play");
        geoFeature.setGeometry(position);
        vectorLayer.un('postrender', moveFeature);
    }

    $(".controlBtn").click(function () {
        if (!stop) {
            if (animating) {
                stopAnimation();
            } else {
                startAnimation();
            }
        } else {
            stop = false;
            distance = 0;
            startAnimation();
        }
    })

    function clearTrack() {
        map.removeLayer(vectorLayer);
        stop = false;
        distance = 0;
        animating = false;
        lastTime = null;
        vectorLayer = null;
        $(".controlBtn > i").removeClass("fa-stop").addClass("fa-play");
        $(".data-control-area").css({"display": "none"})
    }

    //=====航迹 JS ==========//
    /**
     * 新建一条航迹
     */
    function createRoute() {
        //先清除目前存在的的轨迹
        removeFeature(source_const);
        removeFeature(source_modify);
        map.addInteraction(modify);
        map.addInteraction(draw);
        map.addInteraction(snap);
        map.addInteraction(snap_const);
        drawing = true;
        selectedRoute = {};
    }

    function removeFeature(source) {
        var features = source.getFeatures();
        features.forEach(function (f) {
            source.removeFeature(f);
        });
    }

    function getCoordinateFromSource(source) {
        var coordinates = [];
        var features = source.getFeatures();
        if (features.length === 0) {
            return coordinates;
        }
        features.forEach(function (f) {
            var geometry = f.getGeometry();
            var coordinate = geometry.getCoordinates();
            coordinate.forEach(function (p) {
                if (coordinates.length === 0 || !isSamePoint(coordinates.at(-1), p)) {
                    coordinates.push(p);
                }
            })
        })
        return coordinates;
    }

    function isNeedType(type, typeArray) {
        for (let i = 0; i < typeArray.length; i++) {
            if (type === typeArray[i]) {
                return true;
            }
        }
        return false;
    }

    //判断两个坐标点是否相同
    function isSamePoint(p1, p2) {
        return p1[0] === p2[0] && p1[1] === p2[1];
    }

    function saveRoute() {
        //从modify source中取有没有需要保存的点，这里只保存新建的点
        if (selectedRoute.status === undefined ||
            selectedRoute.status === routeType.navRoute ||
            selectedRoute.status === routeType.newRoute) {
            var newRouteFeature = getTheRouteFeature(source_modify.getFeatures());
            var constCoordinates = getCoordinateFromSource(source_const);
            var newRouteCoordinates = [];
            if (newRouteFeature !== undefined) {
                newRouteCoordinates = newRouteFeature.getGeometry().getCoordinates();
                if(constCoordinates.length > 0 && newRouteCoordinates.length > 0
                    && isSamePoint(newRouteCoordinates[0],constCoordinates[constCoordinates.length - 1])){
                    //需要移除newRouteFeature的第一个点
                    newRouteCoordinates.shift();
                }
            }
            openPathModifyPage(newRouteCoordinates);
        } else {
            layer.alert("无法操作！");
        }
    }

    function searchRoute() {
        cleanRoute();
        $.table.search();
    }

    function removeRoute() {
        if (selectedRoute === undefined) {
            layer.alert("请先选择一条航线");
            return;
        }
        $.modal.confirm('确认删除该航线?', () => {
            fetch('/boat/path/remove', {
                method: 'post',
                body:
                    'ids=' + selectedRoute.id,
                headers: {
                    "Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                }
            })
                .then(res => res.json()) //这里必须要先转换一下
                .then(function (res) {
                    if (res.redirected) {
                        if (res.url.includes('login')) {
                            layer.alert('登录状态失效，请重新登录')
                        }
                        window.location.replace(res.url)
                    } else if (res.code === 0) {
                        $.modal.msg('删除成功', modal_status.SUCCESS)
                        $.table.refresh();
                    } else {
                        $.modal.msg(res.msg, modal_status.FAIL)
                    }
                })
        })
    }

    function refreshRouteTable() {
        $.table.refresh();
    }

    function cleanRoute() {
        removeFeature(source_const);
        removeFeature(source_modify);
        selectedRoute = {};
    }

    /**
     * 打开添加path的弹窗页面
     */
    function openPathModifyPage(coordinates) {
        layer.open({
            type: 2,//该类型为跳转到页面
            area: ['800px', '600px'],
            fix: false, // 不固定
            shade: 0.3,
            title: '新增航迹',
            content: "/boat/path/add",
            btn: ['确定', '关闭'],
            shadeClose: false,
            closeBtn: 0,
            yes: function (index, layero) {
                //1.获取子页面的数据，更新planRoute
                var pathData = window[layero.find('iframe')[0]['name']].getPathData();
                console.log(pathData);
                if (pathData.routeName === '') {
                    layer.alert("航迹名称不能为空");
                    return;
                }
                //这里需要判断是新建航迹 or 在已经运行的航迹上做增加航迹点或者修改的动作
                var length = getCoordinateFromSource(source_const, [routeType.navRoute]).length + pathData.pathPoints.length;
                if ((pathData.pathId > 0 && length > 0) ||
                    (pathData.pathId === '' && pathData.coordinates.length >= 2)) {
                    savePathDataToDatabase(pathData);
                } else {
                    layer.alert("新建航迹至少需要2个坐标点！");
                    return;
                }
                //3.关闭弹窗
                layer.close(index);
            },
            cancel: function (layero, index) {
                //执行取消操作
                layer.close(index);
            },
            success: function (layero, index) {
                //把数据传入到 子页面
                $(layero).find('iframe')[0].contentWindow.decorateAddPathPage({
                    "boatCode": [[${boat.code}]],
                    "coordinates": coordinates,
                    'routeName': selectedRoute['name'],//测试用的名称,后期会替换成 currentPathName
                    'pathId': selectedRoute['id'],
                    'status': selectedRoute['status'],//传入status
                });
            }
        });
    }

    function savePathDataToDatabase(data) {
        $.ajax({
            type: "POST",
            url: "/boat/path/add",
            dataType: "json",
            data: [{"name": "name", "value": data.routeName},
                {"name": "status", "value": data.status},
                {"name": "boatCode", "value": data.boatCode},
                {"name": "id", "value": data.pathId},
                {"name": "pathPointListJson", "value": JSON.stringify(data.pathPoints)}],
            success: function (response) {
                if (selectedRoute.id === undefined) {
                    //如果是新建的航迹就刷新table
                    $.table.refresh();
                } else {
                    drawRoute(response.data);
                    selectedRoute = response.data;
                }
            },
            error: function () {
                layer.alert("新建或者编辑航线失败！");
            }
        });
    }

    /**
     * 渲染 航迹
     * @param Path 表格中的一行数据
     */
    function getRouteAndDraw(path) {
        $.ajax({
            type: "GET",
            url: "/boat/path/get/" + path.id,
            dataType: "json",
            success: function (response) {
                console.log(response);
                drawRoute(response);
            },
            error: function (response) {
                console.log(response);
            }
        })
    }

    /**
     * 渲染一条航迹
     * @param path
     */
    function drawRoute(path) {
        var constRouteCoords = [];//已经发送到艇的点位
        var modifyRouteCoords = [];//还未发送到艇的点位
        path.pathPointList.forEach(function (p) {
            if (p.isSend) {
                constRouteCoords.push([p.lng, p.lat]);
            } else {
                modifyRouteCoords.push([p.lng, p.lat]);
            }
        });
        if (modifyRouteCoords.length > 0 && constRouteCoords.length > 0) {
            modifyRouteCoords.unshift(constRouteCoords.at(-1));
        }
        cleanRoute();
        selectedRoute = path;
        if (path.status === routeType.completeRoute) {
            //已经正常结束航行
            addFeatureToSource(source_const, colorOption.completeRoute, constRouteCoords);
        } else if (path.status === routeType.navRoute) {
            //正在航行中
            if (constRouteCoords.length > 0) {
                addFeatureToSource(source_const, colorOption.navRoute, constRouteCoords);
            }
            if (modifyRouteCoords.length > 0) {
                addFeatureToSource(source_modify, colorOption.newRoute, modifyRouteCoords, routeType.newRoute);
            }
        } else if (path.status === routeType.cancelRoute) {
            //航行到半路取消了
            if (constRouteCoords.length > 0) {
                addFeatureToSource(source_const, colorOption.cancelRoute, constRouteCoords);
            }
            if (modifyRouteCoords.length > 0) {
                addFeatureToSource(source_modify, colorOption.cancelRoute, modifyRouteCoords);
            }
        } else if (path.status === routeType.newRoute) {
            //新建
            if (modifyRouteCoords.length > 0) {
                addFeatureToSource(source_modify, colorOption.newRoute, modifyRouteCoords, routeType.newRoute);
            }
        }
    }

    function addFeatureToSource(source, color, coordinates, featureTag) {
        var feature = new ol.Feature(new ol.geom.LineString(coordinates));
        feature.setStyle(getLineStyle(color, 2));
        if (featureTag !== undefined) {
            feature.set('routeType', featureTag);
        }
        source.addFeature(feature);
    }

    function modifyRoute() {
        if (selectedRoute.status === undefined ||
            selectedRoute.status === routeType.newRoute ||
            selectedRoute.status === routeType.navRoute) {
            drawing = true;
            map.addInteraction(modify);
            map.addInteraction(draw);
            map.addInteraction(snap);
            map.addInteraction(snap_const);
        } else {
            layer.alert("无法操作！");
        }
    }

    function sendRoute() {
        if (selectedRoute.id === undefined) {
            $.modal.msg("请先选择一条航迹",modal_status.FAIL);
            return;
        }
        if (selectedRoute.status === routeType.completeRoute
            || selectedRoute.status === routeType.cancelRoute
            || selectedRoute.status === routeType.editRoute
            || (selectedRoute.status === routeType.navRoute && source_modify.getFeatures().length === 0)) {
            $.modal.msg("该航迹已发送或已结束",modal_status.FAIL);
            return;
        }

        if(source_modify.getFeatures().length > 4){
            $.modal.msg("每次最多下发4个航迹点",modal_status.FAIL);
            return;
        }
        $.modal.loading('航迹发送中');
        fetch('/cmd/ctrl', {
            method: 'post',
            body: JSON.stringify({
                boatCode: [[${boat.code}]],
                cmdCode: "path",
                value: selectedRoute.id,
            }),
            headers: {
                'Content-Type': 'application/json;charset=UTF-8',
            }
        }).then(res => res.json()).then(function (res) {
            $.modal.closeLoading();
            if (res.redirected) {
                if (res.url.includes('login')) {
                    layer.alert('登录状态失效，请重新登录')
                }
                window.location.replace(res.url)
            } else if (res.code === 0) {
                $.modal.msg('发送成功', modal_status.SUCCESS);
                $.table.refresh();
            } else {
                $.modal.msg(res.msg, modal_status.FAIL)
            }
        }).catch((reason) => {
            $.modal.closeLoading();
            $.modal.msg('网络连接失败', modal_status.FAIL)
        })
    }
</script>
</body>
</html>